/**
 * BaseDao.java
 * Copyright (C) 2013 Gank
 * Simple Currency Trade System
 * 
 */
package com.gank.ct.common;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

/**
 * Copyright (C) 2013:Gank<br/>
 * Project:Curreny Trade<br/>
 * Module ID:<br/>
 * Comments:Simple Currency Trade System<br/>
 * JDK version used:JDK1.6<br/>
 * Package:com.gank.ct.common<br/>
 * Author:Michael Wu<br/>
 * Create Date:2013-11-3<br/>
 * Modified By:<br/>
 * Modified Date:<br/>
 * Why & What is modified:<br/>
 * Version:0.1<br/>
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class BaseDao<T, ID extends Serializable> extends HibernateDaoSupport
		implements IBaseDao<T, ID> {
	public Logger logger = Logger.getLogger(this.getClass());
	protected Class<T> entityClass;

	public BaseDao() {

	}

	protected Class getEntityClass() {
		if (entityClass == null) {
			entityClass = (Class<T>) ((ParameterizedType) getClass()
					.getGenericSuperclass()).getActualTypeArguments()[0];
			logger.debug("T class = " + entityClass.getName());
		}
		return entityClass;
	}

	public void saveOrUpdate(T t) throws DataAccessException {
		this.getHibernateTemplate().saveOrUpdate(t);
	}

	public T load(ID id) throws DataAccessException {
		T load = (T) getHibernateTemplate().load(getEntityClass(), id);
		return load;
	}

	public T get(ID id) throws DataAccessException {
		T load = (T) getHibernateTemplate().get(getEntityClass(), id);
		return load;
	}

	public boolean contains(T t) throws DataAccessException {
		return getHibernateTemplate().contains(t);
	}

	public void delete(T t, LockMode lockMode) throws DataAccessException {
		getHibernateTemplate().delete(t, lockMode);
	}

	public void delete(T t) throws DataAccessException {
		getHibernateTemplate().delete(t);
	}

	public void deleteAll(Collection<T> entities) throws DataAccessException {
		getHibernateTemplate().deleteAll(entities);
	}

	public List<T> find(String queryString, Object value)
			throws DataAccessException {
		List<T> find = (List<T>) getHibernateTemplate()
				.find(queryString, value);
		return find;
	}

	public List<T> findByCriteria(DetachedCriteria criteria)
			throws DataAccessException {
		List<T> find = (List<T>) getHibernateTemplate()
				.findByCriteria(criteria);
		return find;
	}

	public List<T> find(String queryString, Object[] values)
			throws DataAccessException {
		List<T> find = (List<T>) getHibernateTemplate().find(queryString,
				values);
		return find;
	}

	/**
	 * query.list()它们都将返回一个 Object 数组（Object[]）组成的 List，数组每个元素都是 表的一个字段值
	 * 
	 * @param queryString
	 * @param params
	 * @return
	 * @throws DataAccessException
	 */

	public List<T> findBySQL(final String queryString,
			final Map<String, Object> valueParams,
			final Map<String, Class> entityParams) throws DataAccessException {

		List<T> find = getHibernateTemplate().executeFind(
				new HibernateCallback() {

					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						SQLQuery query = session.createSQLQuery(queryString);

						Set<String> valueKeySet = valueParams.keySet();
						Iterator<String> valueIterator = valueKeySet.iterator();
						while (valueIterator.hasNext()) {
							String key = valueIterator.next();
							query.setParameter(key, valueParams.get(key));
						}
						Set<String> entityKeySet = entityParams.keySet();
						Iterator<String> entityIterator = entityKeySet
								.iterator();
						while (entityIterator.hasNext()) {
							String key = entityIterator.next();
							query.addEntity(key, entityParams.get(key));
						}

						return (List<T>) query.list();

					}

				});

		return find;
	}

	public List<T> find(String queryString) throws DataAccessException {
		return (List<T>) getHibernateTemplate().find(queryString);
	}

	public void refresh(T t, LockMode lockMode) throws DataAccessException {
		getHibernateTemplate().refresh(t, lockMode);
	}

	public void refresh(T t) throws DataAccessException {
		getHibernateTemplate().refresh(t);
	}

	public Serializable save(T t) throws DataAccessException {
		return getHibernateTemplate().save(t);
	}

	public void saveOrUpdateAll(Collection<T> entities)
			throws DataAccessException {
		getHibernateTemplate().saveOrUpdateAll(entities);
	}

	public void update(T t, LockMode lockMode) throws DataAccessException {
		getHibernateTemplate().update(t, lockMode);
	}

	public void update(T t) throws DataAccessException {
		getHibernateTemplate().update(t);
	}

	public List<T> list() throws DataAccessException {
		return getHibernateTemplate().loadAll(getEntityClass());

	}

	public List<T> findByNamedQuery(String queryName)
			throws DataAccessException {
		return getHibernateTemplate().findByNamedQuery(queryName);
	}

	public List<T> findByNamedQuery(String queryName, Object value)
			throws DataAccessException {
		return getHibernateTemplate().findByNamedQuery(queryName, value);
	}

	public List<T> findByNamedQuery(String queryName, Object[] values)
			throws DataAccessException {
		return getHibernateTemplate().findByNamedQuery(queryName, values);
	}

}
